const CFG = require('../config');
const redis = require('redis');
const RedisClient = redis.createClient(CFG.Redis);

RedisClient.on('connect',()=>console.log('[redis] connected'));
RedisClient.on('ready',()=>console.log('[redis] ready'));
RedisClient.on('error',err=>console.log('[redis] err',err));

module.exports = class RedisCache
{
  static N_Config = 'dev-config'; // 设备开机启动的配置项存放
  static N_Policy = 'policy-dev'; // 设备策略配置项(devId键)
  static N_PolicyId = 'policy-id'; // 设备策略配置项(id键)
  static N_Alive = 'alive-dev'; // 在线设备的变量同步缓存，供web socket使用
  static N_Ptype = 'policy-type'; // 策略型号选项
  static N_UserAuth = 'user-auth'; // 用户token等信息

  // 全局函数
  // 搜索指定节点，返回节点名数组，支持通配符
  // 可用type命令判断返回的节点类型
  static keys(prefix,name=null){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.keys(nodeName,function(err,res){
        //console.log('getKey ',err,res);
        if(err) reject(err);
        else resolve(res);
      })
    })
  }

  // 删除，key或hash都用这个函数，删除整个节点请用delNode
  static del(prefix,name=null){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.del(nodeName,function(err){
        //console.log('del ',err);
        if(err) reject(err);
        else resolve(null);
      })
    })
  }

  // 删除节点下面的所有内容
  static async delNode(prefix){
    await RedisClient.keys(prefix+':*',async (err,keys)=>{
      if(keys.length) await RedisClient.del(keys);
    })
  }

  // for key
  // 过期单位为秒
  static setKey(prefix,name,value,expire=0){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.set(nodeName,value,function(err){
        //console.log('setKey ',err);
        if(err){reject(err);}
        else
        {
          resolve(null);
          if(expire) RedisClient.expire(nodeName,expire);
        }
      })
    })
  }

  static incKey(prefix,name,expire=0,val=1){
    let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
    return new Promise(function(resolve,reject){
      RedisClient.incrby(nodeName,val,function(err,res){
        //console.log('getKey ',err,res);
        if(err){reject(err);}
        else
        {
          resolve(res);
          if(expire) RedisClient.expire(nodeName,expire);
        }
      })
    })
  }

  static getKey(prefix,name=null){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.get(nodeName,function(err,res){
        //console.log('getKey ',err,res);
        if(err) reject(err);
        else resolve(res);
      })
    })
  }

  static hasKey(prefix,name=null){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.exists(nodeName,function(err,res){
        //console.log('hasKey',err,res);
        if(err) reject(err);
        else resolve(res);
      })
    })
  }

  // for hash
  // 过期单位为秒
  static set(prefix,name,obj,expire=0){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.hmset(nodeName,obj,function(err){
        //console.log('hmset ',err);
        if(err){reject(err);}
        else
        {
          if(expire) RedisClient.expire(nodeName,expire);
          resolve(null);
        }
      })
    })
  }

  // 自增自减
  static valInt(prefix,name,subKey){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.hincrby(nodeName,subKey,1,function(err,res){
        //console.log('hincrby ',err,res);
        if(err) reject(err);
        else resolve(res);
      })
    })
  }

  // 获取单个子值
  static get(prefix,name,subKey){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.hget(nodeName,subKey,function(err,res){
        //console.log('hget ',err,res);
        if(err) reject(err);
        else resolve(res);
      })
    })
  }

  // 获取hash所有子值
  static getAll(prefix, name, Info=null){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.hgetall(nodeName,function(err,res){
        //console.log('hgetall ',err,res);
        if(err){reject(err);}
        else
        {
          if(res!=null && Info!=null) res.Info=Info;
          resolve(res);
        }
      })
    })
  }

  // 判断hash对象里其中一个键值在不在
  static exists(prefix,name,subKey){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.hexists(nodeName,subKey,function(err,res){
        //console.log('hexists',err,res);
        if(err) reject(err);
        else resolve(res);
      })
    })
  }

  // 删除hash里面一个子值
  static hdel(prefix,name,subKey){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.hdel(nodeName,subKey,function(err,res){
        //console.log('hdel ',err);
        if(err) reject(err);
        else resolve(res);
      })
    })
  }

  // for list
  static push(prefix,name,obj,expire=0){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.rpush(nodeName,obj,function(err){
        //console.log('hmset ',err);
        if(err){reject(err);}
        else
        {
          if(expire) RedisClient.expire(nodeName,expire);
          resolve(null);
        }
      })
    })
  }

  // 先进先出
  static pop(prefix,name=null){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.lpop(nodeName,function(err,res){
        //console.log('hget ',err,res);
        if(err) reject(err);
        else resolve(res);
      })
    })
  }

  // 获取列表在给定范围上的所有值，并不删除列表内容
  static fetchAll(prefix,name=null){
    return new Promise(function(resolve,reject){
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.lrange(nodeName,0,-1,function(err,res){
        //console.log('hget ',err,res);
        if(err) reject(err);
        else resolve(res);
      })
    })
  }

  // 设置过期时间
  static expire(prefix, name, expire_s){
    return new Promise(function(resolve,reject) {
      let nodeName=(name!=null&&name!='')?prefix+':'+name:prefix;
      RedisClient.expire(nodeName, expire_s, function(err){
        if(err) reject(err);
        else resolve(null);
      })
    })
  }


  // rpush 将给定值推入列表的右端 当前列表长度 rpush('key', 'value1' [,'value2']) (支持数组赋值)
  // lrange 获取列表在给定范围上的所有值 array lrange('key', 0, -1) (返回所有值)
  // lindex 获取列表在给定位置上的单个元素 lindex('key', 1)
  // lpop 从列表左端弹出一个值，并返回被弹出的值 lpop('key')
  // rpop 从列表右端弹出一个值，并返回被弹出的值 rpop('key')
  // ltrim 将列表按指定的index范围裁减,只保留指定区间内的元素 ltrim('key', 'start', 'end')


}

